package work.thread_eg.pool;

import cn.hutool.core.date.DateUtil;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

/**
 * 定时线程池的使用
 *
 * 周期性的线程池, 支持定时及周期性执行任务
 *
 * 特点
 *      1 最大线程数 maximumPoolSize是Integer类型的最大值, 不会触发拒绝策略
 *      2 需要指定核心线程数
 *
 * 使用注意：
 *      1 ScheduledExecutorService接口的默认实现类是 ScheduledThreadPoolExecutor
 *      2 在周期执行的任务中,如果任务执行时间大于周期时间, 则会以任务时间优先 , 等任务执行完毕后才会进入下一次周期
 *
 */
public class ScheduledExecutorServiceMain {
    public static void main(String[] args) {
        // 指定核心线程数
        ScheduledExecutorService executorService = Executors.newScheduledThreadPool(3);
        System.out.println(DateUtil.now() + " 提交任务");

        // 1 schedule()方法只执行一次  可以设置延迟启动的时间
        executorService.schedule(() -> {
            // 获取线程名称,默认格式:pool-1-thread-1
            Thread thread = Thread.currentThread();

            // 设置为守护线程 随主线程关闭而关闭
            thread.setDaemon(true);
            System.out.println(DateUtil.now() + "  " + thread.getName());
        }, 5, TimeUnit.SECONDS);

        // 2 scheduleAtFixedRate()方法可以周期性执行  可以设置延迟启动的时间 可以设置周期执行的时间
        // 任务执行时间大于周期时间时 任务结束后会立即进入下一周期
        executorService.scheduleAtFixedRate(() -> {
            // 获取线程名称,默认格式:pool-1-thread-1
            Thread thread = Thread.currentThread();
            System.out.println(DateUtil.now() + "  " + thread.getName());
            try {
                thread.sleep(4000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, 0, 3, TimeUnit.SECONDS);


        // 3 scheduleAtFixedRate() 也能延迟和周期性执行
        // 无论任务时间是否超过，都将会在你任务执行完毕后延迟固定秒数(也就是delay的值) 才会进入下一周期
        // 周期时间 = delay的值 + 线程本身执行的时间
        executorService.scheduleWithFixedDelay(() -> {
            Thread thread = Thread.currentThread();
            System.out.println(DateUtil.now() + "  " + thread.getName());
            try {
                thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }, 0, 3, TimeUnit.SECONDS);


    }

    public static void sleep(int time) {
        try {
            Thread.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
